//
//  tdInterface.c
//  
//
//  Created by Preston Skaggs on 2/20/14.
//  This is a modified version of the interface.c file
//  
//


#include "tdInterface.h"


/*-----------------------------
 Convert card number to string
 ----------------------------*/
void cardNumToName(int card, char *name){
    switch(card){
        case curse: strcpy(name,"Curse");
            break;
        case estate: strcpy(name,"Estate");
            break;
        case duchy: strcpy(name,"Duchy");
            break;
        case province: strcpy(name,"Province");
            break;
        case copper: strcpy(name,"Copper");
            break;
        case silver: strcpy(name,"Silver");
            break;
        case gold: strcpy(name,"Gold");
            break;
        case adventurer: strcpy(name,"Adventurer");
            break;
        case council_room: strcpy(name,"Council Room");
            break;
        case feast: strcpy(name,"Feast");
            break;
        case gardens: strcpy(name,"Gardens");
            break;
        case mine: strcpy(name,"Mine");
            break;
        case remodel: strcpy(name,"Remodel");
            break;
        case smithy: strcpy(name,"Smithy");
            break;
        case village: strcpy(name,"Village");
            break;
        case baron: strcpy(name,"Baron");
            break;
        case great_hall: strcpy(name,"Great Hall");
            break;
        case minion: strcpy(name,"Minion");
            break;
        case steward: strcpy(name,"Steward");
            break;
        case tribute: strcpy(name,"Tribute");
            break;
        case ambassador: strcpy(name,"Ambassador");
            break;
        case cutpurse: strcpy(name,"Cutpurse");
            break;
        case embargo: strcpy(name,"Embargo");
            break;
        case outpost: strcpy(name,"Outpost");
            break;
        case salvager: strcpy(name,"Salvager");
            break;
        case sea_hag: strcpy(name,"Sea Hag");
            break;
        case treasure_map: strcpy(name,"Treasure Map");
            break;
            
        default: strcpy(name,"?");
    }
    
}



int getCardCost(int card) {
    int cost;
    switch(card) {
        case curse: cost = CURSE_COST;
            break;
        case estate: cost = ESTATE_COST;
            break;
        case duchy: cost = DUCHY_COST;
            break;
        case province: cost = PROVINCE_COST;
            break;
        case copper: cost = COPPER_COST;
            break;
        case silver: cost = SILVER_COST;
            break;
        case gold: cost = GOLD_COST;
            break;
        case adventurer: cost = ADVENTURER_COST;
            break;
        case council_room: cost = COUNCIL_ROOM_COST;
            break;
        case feast: cost = FEAST_COST;
            break;
        case gardens: cost = GARDEN_COST;
            break;
        case mine:  cost = MINE_COST;
            break;
        case remodel: cost = REMODEL_COST;
            break;
        case smithy: cost = SMITHY_COST;
            break;
        case village: cost = VILLAGE_COST;
            break;
        case baron: cost = BARON_COST;
            break;
        case great_hall: cost = GREAT_HALL_COST;
            break;
        case minion: cost = MINION_COST;
            break;
        case steward: cost = STEWARD_COST;
            break;
        case tribute: cost = TRIBUTE_COST;
            break;
        case ambassador: cost = AMBASSADOR_COST;
            break;
        case cutpurse: cost = CUTPURSE_COST;
            break;
        case embargo: cost = EMBARGO_COST;
            break;
        case outpost: cost = OUTPOST_COST;
            break;
        case salvager: cost = SALVAGER_COST;
            break;
        case sea_hag: cost = SEA_HAG_COST;
            break;
        case treasure_map: cost = TREASURE_MAP_COST;
            break;
        default: cost = ONETHOUSAND;
    }
    return cost;
}






void printHand(int player, struct gameState *game) {
    int handCount = game->handCount[player];
    int handIndex;
    FILE *fd = fopen("gameResults.out", "a");
    if(fd == NULL){
        printf("Failed to open file");
        exit(1);
    }
    fprintf(fd,"Player %d's hand:\n", player);
    if(handCount > 0) fprintf(fd,"#  Card\n");
    for(handIndex = 0; handIndex < handCount; handIndex++) {
        int card = game->hand[player][handIndex];
        char name[MAX_STRING_LENGTH];
        cardNumToName(card, name);
        fprintf(fd,"%-2d %-13s\n", handIndex, name);
    }
    fprintf(fd,"\n");
    fclose(fd);
}



void printDeck(int player, struct gameState *game) {
    int deckCount = game->deckCount[player];
    int deckIndex;
    FILE *fd = fopen("gameResults.out", "a");
    if(fd == NULL){
        printf("Failed to open file");
        exit(1);
    }
    fprintf(fd,"Player %d's deck: \n", player);
    if(deckCount > 0) fprintf(fd,"#  Card\n");
    for(deckIndex = 0; deckIndex < deckCount; deckIndex++) {
        int card = game->deck[player][deckIndex];
        char name[MAX_STRING_LENGTH];
        cardNumToName(card, name);
        fprintf(fd,"%-2d %-13s\n", deckIndex, name);
    }
    fprintf(fd,"\n");
    fclose(fd);
}

void printPlayed(int player, struct gameState *game) {
    int playedCount = game->playedCardCount;
    int playedIndex;
    FILE *fd = fopen("gameResults.out", "a");
    if(fd == NULL){
        printf("Failed to open file");
        exit(1);
    }
    fprintf(fd,"Player %d's played cards: \n", player);
    if(playedCount > 0) fprintf(fd,"#  Card\n");
    for(playedIndex = 0; playedIndex < playedCount; playedIndex++) {
        int card = game->playedCards[playedIndex];
        char name[MAX_STRING_LENGTH];
        cardNumToName(card, name);
        fprintf(fd,"%-2d %-13s \n", playedIndex, name);
    }
    fprintf(fd,"\n");
    fclose(fd);
}



void printDiscard(int player, struct gameState *game) {
    int discardCount = game->discardCount[player];
    int discardIndex;
    FILE *fd = fopen("gameResults.out", "a");
    if(fd == NULL){
        printf("Failed to open file");
        exit(1);
    }
    fprintf(fd,"Player %d's discard: \n", player);
    if(discardCount > 0) fprintf(fd,"#  Card\n");
    for(discardIndex = 0; discardIndex < discardCount; discardIndex++) {
        int card = game->discard[player][discardIndex];
        char name[MAX_STRING_LENGTH];
        cardNumToName(card, name);
        fprintf(fd,"%-2d %-13s \n", discardIndex, name);
    }
    fprintf(fd,"\n");
    fclose(fd);
}




void printSupply(struct gameState *game) {
    int cardNum, cardCost, cardCount;
    char name[MAX_STRING_LENGTH];
    FILE *fd = fopen("gameResults.out", "a");
    if(fd == NULL){
        printf("Failed to open file");
        exit(1);
    }
    fprintf(fd,"#   Card          Cost   Copies\n");
    for(cardNum = 0; cardNum < NUM_TOTAL_K_CARDS; cardNum++){
        cardCount = game->supplyCount[cardNum];
        if(cardCount == -1) continue;
        cardNumToName(cardNum, name);
        cardCost = getCardCost(cardNum);
        fprintf(fd,"%-2d  %-13s %-5d  %-5d", cardNum, name, cardCost, cardCount);
        fprintf(fd,"\n");
    }
    fprintf(fd,"\n");
    fclose(fd);
}


void printState(struct gameState *game) {
    int numActions = game->numActions;
    int numCoins = game->coins;
    int numBuys = game->numBuys;
    int currentPlayer = game->whoseTurn;
    int phase = game->phase;
    char phaseName[MAX_STRING_LENGTH];
    FILE *fd = fopen("gameResults.out", "a");
    if(fd == NULL){
        printf("Failed to open file");
        exit(1);
    }
    phaseNumToName(phase,phaseName);
    fprintf(fd,"Player %d:\n%s phase\n%d actions\n%d coins\n%d buys\n\n", currentPlayer, phaseName, numActions, numCoins, numBuys);
    fclose(fd);
}

void printScores(struct gameState *game) {
    int playerNum, score[MAX_PLAYERS];
    int numPlayers = game->numPlayers;
    FILE *fd = fopen("gameResults.out", "a");
    if(fd == NULL){
        printf("Failed to open file");
        exit(1);
    }
    for(playerNum = 0; playerNum < numPlayers; playerNum++) {
        score[playerNum] = scoreFor(playerNum,game);
        fprintf(fd,"Player %d has a score of %d\n", playerNum, score[playerNum]);
    }
    fclose(fd);
}



void phaseNumToName(int phase, char *name) {
    switch(phase){
        case ACTION_PHASE: strcpy(name,"Action");
            break;
        case BUY_PHASE: strcpy(name,"Buy");
            break;
        case CLEANUP_PHASE: strcpy(name,"Cleanup");
            break;
    }
}


int addCardToHand(int player, int card, struct gameState *game) {
    if(card >= adventurer && card < NUM_TOTAL_K_CARDS){
        int handTop = game->handCount[player];
        game->hand[player][handTop] = card;
        game->handCount[player]++;
        return SUCCESS;
    } else {
        return FAILURE;
    }
    
}

/*-----------------------------
 Select Kingdom Cards Randomly
 ----------------------------*/
void selectKingdomCards(int randomSeed, int kingCards[NUM_K_CARDS]) {
    int i, used, card, numSelected = 0;
    SelectStream(1);
	PutSeed((long)randomSeed);
    
	
    while(numSelected < NUM_K_CARDS) {
        used = FALSE;
        card = floor(Random() * NUM_TOTAL_K_CARDS);
        if(card < adventurer) continue;
        for(i = 0; i < numSelected; i++) {
            if(kingCards[i] == card) {
                used = TRUE;
                break;
            }
        }
        if(used == TRUE) continue;
        kingCards[numSelected] = card;
        numSelected++;
    }
}
/*-----------------------------
 Decision Maker
 ----------------------------*/
int decider(){
    int value = 0;
    if(Random() > 0.67) value = 2;
    if(Random() < 0.67 && Random() > .33) value = 1;
    return value;
}
/*-----------------------------
 Count coins
 ----------------------------*/
int countHandCoins(int player, struct gameState *game) {
    int card, index, coinage = 0;
	
    for(index = 0; index < game->handCount[player]; index++) {
        card = game->hand[player][index];
        switch(card) {
            case copper: coinage += 1;
                break;
            case silver: coinage += 2;
                break;
            case gold: coinage += 3;
                break;
        }
    }
    return coinage;
}

/*-----------------------------
 Execute Computer's Buy
 ----------------------------*/
void botBuysCard(int player, struct gameState *game, int *kCards){
    int coins = countHandCoins(player, game);
    int decision= decider();
    int kingdomCardBought = FALSE;
    int loopCount = 0;
    int card = 0;
    
    char cardName[MAX_STRING_LENGTH];
    FILE *fd = fopen("./gameResults.out", "a");
    if(fd == NULL){
        printf("Failed to open file");
        exit(1);
    }
    fprintf(fd,"coins %d\n", coins);
    if(coins >= getCost(province) && supplyCount(province,game) > 0) {
        /*this could be randomized to select any card but
         this is the best way for a player to win*/
        fprintf(fd,"Player %d buys card Province\n\n", player);
        buyCard(province,game);
    }
    else if(coins < getCost(province) && coins >= getCost(gold)) {
        if(decision == 2 && supplyCount(duchy, game) > 0){
            fprintf(fd,"Player %d buys card Duchy\n\n", player);
            buyCard(duchy,game);
        }
        else if(decision == 1){
            //there is a 10% chance the computer will buy a treasure other than gold
            if(Random() > 0.1 && supplyCount(gold, game) > 0){
                fprintf(fd,"Player %d buys card Gold\n\n", player);
                buyCard(gold, game);

            }
            else if (supplyCount(silver, game) > 0){
                fprintf(fd,"Player %d buys card Silvern\n", player);
                buyCard(silver, game);
            }
            else if(supplyCount(copper, game) > 0){
                fprintf(fd,"Player %d buys card Copper\n\n", player);
                buyCard(copper, game);
            }
        }
        else{
            while(!kingdomCardBought){
                card = floor(Random() * NUM_K_CARDS);
                if(supplyCount(kCards[card], game) > 0){
                    kingdomCardBought = TRUE;
                    cardNumToName(kCards[card], cardName);
                    fprintf(fd,"Player %d buys card %s\n\n", player, cardName);
                    buyCard(kCards[card], game);
                }
            }
            
        }
    }
    else if(coins < getCost(gold) && coins >= getCost(silver)) {
        if(decision == 2 && supplyCount(estate, game) > 0){
            fprintf(fd,"Player %d buys card Estate\n\n", player);
            buyCard(estate,game);
        }
        else if(decision == 1){
            //there is a 10% chance the computer will buy a treasure other than silver
            if(Random() > 0.1 && supplyCount(silver, game) > 0){
                fprintf(fd,"Player %d buys card Silver\n\n", player);
                buyCard(silver, game);
            }
            
            else if(supplyCount(copper, game) > 0){
                fprintf(fd,"Player %d buys card Copper\n\n", player);
                buyCard(copper, game);
            }
        }
        else{
            while(!kingdomCardBought && loopCount < 100){  //loop counter is to avoid scenario where no kingdom card is available for the price
                card = floor(Random() * NUM_K_CARDS);
                if(supplyCount(kCards[card], game) > 0){
                    kingdomCardBought = TRUE;
                    cardNumToName(kCards[card], cardName);
                    fprintf(fd,"Player %d buys card %s\n\n", player, cardName);
                    buyCard(kCards[card], game);
                }
                loopCount++;
            }
            
        }
    }
    else if(coins < getCost(silver) && supplyCount(copper,game) > 0) {
        if(buyCard(copper,game) == -1){
            fprintf(fd,"Unable to buy copper");
            game->numBuys--;
        }
        else
        fprintf(fd,"Player %d buys card Copper\n\n", player);
        
    }
    fclose(fd);
}
/*-----------------------------
 Execute Computer's Action
 ----------------------------*/

void botPlaysAction(int player, struct gameState *game, int handPos){
    int choice1, choice2, choice3;
    char cardName[MAX_STRING_LENGTH];
    FILE *fd = fopen("./gameResults.out", "a");
    if(fd == NULL){
        printf("Failed to open file");
        exit(1);
    }
    cardNumToName(game->hand[player][handPos], cardName);
    choice1 = floor(Random()*NUM_K_CARDS);
    choice2 = floor(Random()*NUM_K_CARDS);
    choice3 = floor(Random()*NUM_K_CARDS);
    fprintf(fd,"Player %d plays card %s\n", player, cardName);
    if(game->hand[player][handPos] == feast){ //playing feast enters an infinite loop
        game->numActions--;
    }
    else playCard(handPos, choice1, choice2, choice3, game);
    fclose(fd);
}
/*-----------------------------
 Execute Computer's Turn
 ----------------------------*/
void executeBotTurn(int player, int *turnNum, struct gameState *game, int *kCards) {
    
	int i, j;
    int handPos = 501;
    FILE *fd = fopen("./gameResults.out", "a");
    if(fd == NULL){
        printf("Failed to open file");
        exit(1);
    }
    fprintf(fd,"*****************Executing Bot Player %d Turn Number %d*****************\n", player, *turnNum);
    printSupply(game);
    printHand(player, game);
    
    fprintf(fd,"Player %d numBuys %d numActions %d\n", game->whoseTurn, game->numBuys, game->numActions);
    //sleep(1); //Thinking...
    //Play the first action card in the hand if any
    
	//This while loop causes problems with action cards like Treasure Map when action and buys aren't decremented
    //while(game->numBuys >0){
        //handPos = 501;
        for(i = 0; i< game->handCount[player]; i++){
            for (j = 0; j<NUM_K_CARDS; j++){
                if(game->hand[player][i] == kCards[j]){
                    handPos = i;
                    break;
                }
            }
        }
        if(handPos != 501 && game->numActions > 0){
            if(game->hand[player][handPos] == gardens || game->hand[player][handPos] == minion){
                game->numActions--;
            }
            else
            botPlaysAction(player, game, handPos);
        }
        
        else if(game->numBuys >0){
            botBuysCard(player, game, kCards);
        }
    //}
    
    if(player == (game->numPlayers -1)) (*turnNum)++;
    endTurn(game);
    if(! isGameOver(game)) {
        int currentPlayer = whoseTurn(game);
        fprintf(fd,"Player %d's turn number %d\n\n", currentPlayer, (*turnNum));
    }
    fclose(fd);
}
